package main

import (
	"fmt"
	"iot-base/common/cache"
	"iot-base/common/ctrltype"
	"iot-base/common/logger"
	"iot-base/common/modbus"

	"errors"
	"strconv"
	"time"
)

func Control(pCmd *ctrltype.CtrlCmd) (map[string]interface{}, error) {
	thing, _ := cache.GetThing(pCmd.ThingID)
	ty, ok := thing.Params["type"]
	if !ok {
		logger.Log.Error("type err")
		return nil, errors.New("type err")
	}
	ip, ok := thing.Params["IP"]
	if !ok {
		fmt.Println("IP err")
		return nil, errors.New("ip err")
	}
	port, ok := thing.Params["Port"]
	if !ok {
		fmt.Println("port err")
		return nil, errors.New("port err")
	}
	slaveID, ok := thing.Params["slaveID"]
	if !ok {
		fmt.Println("slaveID err")
		return nil, errors.New("slaveID err")
	}
	id, ok := thing.Params["id"]
	if !ok {
		fmt.Println("id err")
		return nil, errors.New("id err")
	}
	client := new(modbus.Client)
	switch ty {
	case "dtu":
		confip := ip + ":" + port
		if cli, ok := connection[confip]; !ok {
			slaveid, err := strconv.ParseUint(slaveID, 10, 0)
			handler := modbus.NewDTUClientHandler(confip)
			handler.SlaveId = uint8(slaveid)
			handler.Timeout = 500 * time.Millisecond
			err = handler.Connect()
			if err != nil {
				fmt.Println("dtu connect err!")
				return nil, errors.New("dtu connect err")
			}
			*client = modbus.NewClient(handler)
			connection[confip] = *client
		} else {
			*client = cli
		}
		fmt.Println("serial start:------------------------------", *client)
		mux.Lock()
		msg, err := SendSv(id, pCmd, *client)
		mux.Unlock()
		return msg, err
	case "tcp":
		slaveid, err := strconv.ParseUint(slaveID, 10, 0)
		handler := modbus.NewTCPClientHandler(fmt.Sprintf("%s:%s", ip, port))
		handler.SlaveId = uint8(slaveid)
		handler.Timeout = 500 * time.Millisecond
		err = handler.Connect()
		if err != nil {
			fmt.Println("tcp connect err!")
			return nil, errors.New("tcp connect err")
		}
		defer handler.Close()
		*client = modbus.NewClient(handler)
		fmt.Println("tcp start:------------------------------", *client)
		return SendSv(id, pCmd, *client)
	default:
		logger.Log.Error("no this type")
		return nil, errors.New("no this type")
	}
	return nil, errors.New("no this type")
}

func SendSv(id string, pCmd *ctrltype.CtrlCmd, client modbus.Client) (map[string]interface{}, error) {
	result := make(map[string]interface{})
	value := pCmd.Params["status"]
	var s uint16
	if value == "0" {
		s = 0
	} else if value == "1" {
		s = 65280
	} else {
		return nil, errors.New("value is err")
	}
	switch pCmd.ID {
	case "control":
		switch id {
		case "DO0":
			res, err := client.WriteSingleCoil(0, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO1":
			res, err := client.WriteSingleCoil(1, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO2":
			res, err := client.WriteSingleCoil(2, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO3":
			res, err := client.WriteSingleCoil(3, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO4":
			res, err := client.WriteSingleCoil(4, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO5":
			res, err := client.WriteSingleCoil(5, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO6":
			res, err := client.WriteSingleCoil(6, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		case "DO7":
			res, err := client.WriteSingleCoil(7, s)
			if err != nil {
				return nil, err
			}
			result["msg"] = res
			return result, nil
		default:
			return nil, errors.New("not exist param id")
		}
	default:
		return nil, errors.New("no this serve")
	}
}
